package com.yuyou.fn.educational.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.CriteriaUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.mapper.CourseClassMapper;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.ArrangeClassTimeResultVo;
import com.yuyou.fn.educational.vo.CourseClassQueryVo;
import com.yuyou.fn.educational.vo.CourseClassSaveOrUpdateVo;
import com.yuyou.fn.platform.service.IAreaTeamService;
import com.yuyou.fn.platform.service.IBusTeamService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Transient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Time;
import java.util.*;

/**
 * CourseClass 表数据服务层接口实现类
 */
@Service
public class CourseClassServiceImpl extends SuperServiceImpl<CourseClassMapper, CourseClass, Long> implements ICourseClassService {


    @Resource
    private IAreaTeamService areaTeamService;

    @Resource
    private IBusTeamService busTeamService;

    @Resource
    private ICourseTemplateService iCourseTemplateService;

    @Resource
    private IPeriodService iPeriodService;

    @Resource
    private IRoomService roomService;

    @Resource
    private IRoomTimeService roomTimeService;

    @Resource
    private ITeacherService teacherService;

    @Resource
    private IClassTimeService classTimeService ;

    @Resource
    private IClassTeacherService classTeacherService;

    @Resource
    private IAttendanceRecordService attendanceRecordService;

    @Resource
    private RedisTemplate redisTemplate ;


    @Override
    public Page<CourseClass> findCourseClassByQueryForPage(CourseClassQueryVo courseClassQueryVo, int pageNo, int pageSize) {
        Example<CourseClass> example = CourseClass.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();

        CriteriaUtils.fillCondition(criteria, courseClassQueryVo);

        return findPageByExample(example, pageNo, pageSize);
    }

    @Transactional
    @Override
    public void saveOrUpdateCourseClass(CourseClassSaveOrUpdateVo courseClassSaveOrUpdateVo) {

        CourseClass courseClass = new CourseClass();

        BeanUtils.copyProperties(courseClass, courseClassSaveOrUpdateVo);
        fillExtraData(courseClass);

        checkClassName(courseClass);

        if (courseClass.getClassId() == null) {
            courseClass.setClassNo(createClassNo());
            courseClass.setCreateTime(TimeUtils.now());
            courseClass.setUpdateTime(TimeUtils.now());
            insertSelective(courseClass);
            attendanceRecordService.createAttendanceRecord(courseClass.getClassId(),courseClass.getLectureAmount());
            classTimeService.createClassTime(courseClass.getClassId() , courseClass.getLectureAmount());
        } else {
            courseClass.setUpdateTime(TimeUtils.now());
            updateSelectiveById(courseClass);
        }
    }

    private String createClassNo() {
        Long no = redisTemplate.opsForValue().increment("class_no", 1);
        return StringUtils.leftPad(String.valueOf(no), 6, "0");
    }

    private void checkClassName(CourseClass courseClass) {
        Example<CourseClass> example = CourseClass.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("periodId", courseClass.getPeriodId() ).andEqualTo("className",courseClass.getClassName()) ;

        CourseClass one = findOneByExample(example);

        if(one != null && ( courseClass.getClassId() == null || !one.getClassId().equals(courseClass.getClassId()))){
            throw new BusException("同一期班名重复");
        }
    }

    private void fillExtraData(CourseClass courseClass) {

        if (courseClass.getAreaTeamId() != null) {
            courseClass.setAreaTeamName(areaTeamService.findTeamNameById(courseClass.getAreaTeamId()));
        } else {
            courseClass.setAreaTeamId(0l);
            courseClass.setAreaTeamName("");
        }

        if (courseClass.getBusTeamId() != null) {
            courseClass.setBusTeamName(busTeamService.findTeamNameById(courseClass.getBusTeamId()));
        } else {
            courseClass.setBusTeamId(0l);
            courseClass.setBusTeamName("");
        }


        if (courseClass.getPeriodId() != null && iPeriodService.findById(courseClass.getPeriodId()) != null) {
            Period period = iPeriodService.findById(courseClass.getPeriodId());
            courseClass.setPeriodName(period.getPeriodNo().toString());
        } else {
            courseClass.setPeriodId(0l);
            courseClass.setPeriodName("");
        }

        if ( courseClass.getCourseTemplateId()!=null){
            CourseTemplate courseTemplate = iCourseTemplateService.findById(courseClass.getCourseTemplateId());
            if(courseTemplate != null) {
                courseClass.setLectureAmount(courseTemplate.getLectureAmount());
                courseClass.setLectureDuration(courseTemplate.getLectureDuration());
                courseClass.setMaterialFee(courseTemplate.getMaterialFee());
                courseClass.setSubjectId(courseTemplate.getSubjectId());
                courseClass.setSubjectName(courseTemplate.getSubjectName());
                courseClass.setGradeId(courseTemplate.getGradeId());
                courseClass.setGradeName(courseTemplate.getGradeName());
                courseClass.setProductId(courseTemplate.getProductId());
                courseClass.setSeason(courseTemplate.getSeason());
                courseClass.setLevel(courseTemplate.getLevel());
            }
        }else{
            courseClass.setCourseTemplateId(0l);
            courseClass.setLectureAmount(0);
            courseClass.setLectureDuration(0);
            courseClass.setStudyingFee(new BigDecimal(0));
            courseClass.setMaterialFee(new BigDecimal(0));
            courseClass.setSubjectId(0l);
            courseClass.setSubjectName("");
            courseClass.setGradeId(0l);
            courseClass.setGradeName("");
            courseClass.setLevel(1);
        }

    }

    /**
     * 通过classId找className
     *
     * @param classId
     * @return by Terry
     */
    @Override
    public String findCourseNameById(Long classId) {
        Example<CourseClass> example = CourseClass.createExample();
        example.selectProperties("className");
        example.createCriteria().andEqualTo("classId", classId);
        CourseClass courseClass = findOneByExample(example);
        return courseClass == null ? StringUtils.EMPTY : courseClass.getClassName();
    }

    @Override
    public CourseClass findBaseCourseClass(Long classId) {
        Example<CourseClass> example = CourseClass.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("classId", classId);
        return findOneByExample(example);
    }

    @Transactional
    @Override
    public void saveArrangementRoom(Long classId, Long roomId) {
        roomTimeService.detectConflict(classId,roomId);
        CourseClass courseClass = new CourseClass();
        courseClass.setClassId(classId);
        courseClass.setRoomId(roomId);
        Room room = roomService.findById(roomId);
        courseClass.setCampusId(room.getCampusId());
        courseClass.setCampusName(room.getCampusName());
        courseClass.setRoomName(room.getRoomName());
        courseClass.setIsArrangeRoom(1);
        updateSelectiveById(courseClass);
        roomTimeService.saveOrUpdateRoomTime(classId);
    }

    @Transactional
    @Override
    public void saveArrangementTeacher(Long classId, List<Long> teacherIds) {
        if ( classId==null || teacherIds==null ) throw new BusException("班级id或者教师id为空");
        CourseClass courseClass = new CourseClass();
        courseClass.setClassId(classId);
        //去重
        Set<Long> uniTeacherIds = new HashSet<>();
        for(Long teacherId : teacherIds ){
            uniTeacherIds.add(teacherId);
        }
        courseClass.setTeacherIds(StringUtils.join(uniTeacherIds,","));
        courseClass.setTeacherNames(teacherService.getNamesByIds(teacherIds));
        courseClass.setIsArrangeTeacher(1);
        updateSelectiveById(courseClass);
        classTimeService.saveArrangementTeacher(classId,teacherIds) ;
        classTeacherService.saveTeachers(classId,teacherIds ,2 );//任课老师
    }



    @Override
    public boolean decreaseRegAmount(Long classId) {
        CourseClass courseClass = findById(classId);
        CourseClass update = new CourseClass();
        update.setRegAmount(courseClass.getRegAmount() - 1 );
        Example<CourseClass> example = CourseClass.createExample();
        example.createCriteria().andEqualTo("classId",classId).andEqualTo("regAmount",courseClass.getRegAmount());
        return updateSelectiveByExample(update,example);
    }

    @Transactional
    @Override
    public void saveArrangeClassTimeResult(Long classId, List<ArrangeClassTimeResultVo> arrangeClassTimeResultList) {
        classTimeService.saveArrangeClassTimeResult(classId, arrangeClassTimeResultList);

        Set<String> times = new HashSet<>();
        for(ArrangeClassTimeResultVo vo : arrangeClassTimeResultList ){
            times.add(vo.getTime());
        }

        CourseClass courseClass = new CourseClass();
        courseClass.setClassId(classId);
        courseClass.setIsArrangeTime(1);
        courseClass.setStudyingTime(StringUtils.join(times," "));
        courseClass.setStartCourseTime(TimeUtils.parse(arrangeClassTimeResultList.get(0).getDate(),"yyyy-MM-dd"));
        courseClass.setEndCourseTime(TimeUtils.parse(arrangeClassTimeResultList.get(arrangeClassTimeResultList.size() - 1 ).getDate(),"yyyy-MM-dd"));
        this.updateSelectiveById(courseClass);
    }

    @Override
    public void changeStatus(List<Long> classIds, Integer status) {
        Example<CourseClass> example = CourseClass.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("classId",classIds);
        CourseClass update = new CourseClass();
        update.setStatus(status);
        updateSelectiveByExample(update,example);
    }

    @Override
    public boolean increaseRegAmount(Long classId, Integer nowRegAmount) {
        CourseClass update = new CourseClass();
        update.setRegAmount(nowRegAmount + 1 );
        Example<CourseClass> example = CourseClass.createExample();
        example.createCriteria().andEqualTo("classId",classId).andEqualTo("regAmount",nowRegAmount);
        return updateSelectiveByExample(update,example);
    }

    @Override
    public boolean updateCompletedLectureAmount(Long classId, Integer completedLectureAmount) {
        CourseClass update = new CourseClass();
        update.setCompletedLectureAmount(completedLectureAmount);
        Example<CourseClass> example = CourseClass.createExample();
        example.createCriteria().andEqualTo("classId" , classId ).andEqualTo("completedLectureAmount" , completedLectureAmount - 1);
        return updateSelectiveByExample(update,example );
    }

    @Override
    public void recommendCourseClass(List<Long> classIds, Integer isRecommend) {
        Example<CourseClass> example = CourseClass.createExample();
        example.createCriteria().andIn("classId",classIds);
        CourseClass update = new CourseClass();
        update.setIsRecommend(isRecommend);
        update.setUpdateTime(TimeUtils.now());
        updateSelectiveByExample(update,example);
    }
}